package com.hspedu.mydynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author 谷其昊
 * @version 1.0
 * @date 2022/3/31
 * @time 17:04
 */
public class ProxyTest {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
        String needProxyClass = "com.hspedu.mydynamicproxy.Dog";
        //此时得到了这个被代理类的 Class 类对象，我们就能获取到其实现了哪个接口
        Class<?> cls = Class.forName(needProxyClass);
        //获取其实现了哪个接口
        Class<?>[] interfaces = cls.getInterfaces();
        //获取被代理类
        Object instance = cls.newInstance();
        //根据上面获取到的信息去创建代理类
        Object proxyInstance = Proxy.newProxyInstance(cls.getClassLoader(), interfaces,new MyInvocationHandler(instance) );
        Class<?> proxyInstanceClass = proxyInstance.getClass();
        Method[] declaredMethods = proxyInstanceClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            declaredMethod.invoke(proxyInstance);
        }
    }
}

class MyInvocationHandler implements InvocationHandler{

    private Object obj;

    public MyInvocationHandler(Object obj) {
        System.out.println(obj.getClass());
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(obj.getClass());
        return method.invoke(obj,args);
    }
}

/**
 * 接口
 */
interface Human {
    String getBelief();
    void eat();
}

/**
 * 被代理类
 */
class SuperMan implements Human {
    @Override
    public String getBelief() {
        return "I believe i can fly!";
    }

    @Override
    public void eat() {
        System.out.println("超人喜欢吃汉堡");
    }
}

class HumanProxy implements Human{

    Human target ;

    public HumanProxy(Human target) {
        this.target = target;
    }

    @Override
    public String getBelief() {
        return target.getBelief();
    }

    @Override
    public void eat() {
        target.eat();
    }
}


interface Animal{
    void run();
}

class Dog implements Animal{
    @Override
    public void run() {
        System.out.println("dog run...");
    }
}

class AnimalProxy implements Animal{
    Animal animal;

    public AnimalProxy(Animal animal) {
        this.animal = animal;
    }

    @Override
    public void run() {
        animal.run();
    }
}